﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using FCA.Helper;

namespace FCA.Dto {
    /// <summary>
    /// this is a context in galois
    /// </summary>
    public class Concept {
        #region Properties
        public int ID { get; set; }

        public int Support { get; set; }

        //public TidSet Tids { get; set; }

        //public ItemSet Items { get; set; }

        //public HashSet<int> ParentID { get; set; }

        //public HashSet<int> ChildrenID { get; set; }

        public List<int> Tids { get; set; }
        public List<int> Items { get; set; }
        public List<int> ParentID { get; set; }
        public List<int> ChildrenID { get; set; }

        #endregion

        #region Constructors
        public Concept() {
            ID = -1;
            Support = 0;
            Tids = new List<int>();
            Items = new List<int>();
            ChildrenID = new List<int>();
            ParentID = new List<int>();
        }

        public Concept(int id, int sup, List<int> itemSet, List<int> tidSet)
            : this() {
            ID = id;
            Support = sup;
            Tids = new List<int>(tidSet);
            Items = new List<int>(itemSet);            
        }
        #endregion

        public List<int> GetChildrentID() {
            return new List<int>(ChildrenID);
        }

        public List<int> GetParentID() {
            return new List<int>(ParentID);
        }

        public string GetChildrenIDString() {
            return string.Join(",", ChildrenID);
        }

        public string GetParentIDString() {
            return string.Join(",", ParentID);
        }

        public string GetItemsString() {
            return string.Join(",", Items);
        }

        public string GetTidsString() {
            return string.Join(",", Tids);
        }

        #region get list concept (parents, children)
        public List<Concept> GetChildren(Lattice lat) {
            List<Concept> lst = new List<Concept>();
            foreach (int childID in ChildrenID) {
                if (lat.Concepts.ContainsKey(childID)) {
                    lst.Add(lat.Concepts[childID]);
                }
            }
            return lst;
        }

        public List<Concept> GetParents(Lattice lat) {
            List<Concept> lst = new List<Concept>();
            foreach (int parentID in ParentID) {
                if (lat.Concepts.ContainsKey(parentID)) {
                    lst.Add(lat.Concepts[parentID]);
                }
            }
            return lst;
        }
        #endregion
        #region Add child, parent
        /// <summary>
        /// two way added
        /// </summary>
        /// <param name="c"></param>
        public void AddParent(Concept c) {
            if (ID == c.ID || ParentID.Contains(c.ID)) {
                return;
            }
            ParentID.AddUnique(c.ID);
            c.ChildrenID.AddUnique(ID);
            c.Tids = c.Tids.UnionWith(Tids);
        }

        /// <summary>
        /// one way added
        /// </summary>
        /// <param name="id"></param>
        public void AddParent(int id) {
            ///if (id == ID || ParentID.Contains(id)) {
            if (id == ID) {
                return;
            }
            ParentID.AddUnique(id);
        }

        /// <summary>
        /// two way added
        /// </summary>
        /// <param name="id"></param>
        /// <param name="lat"></param>
        public void AddParent(int id, Lattice lat) {
            //if (ID == id || ParentID.Contains(id)) {
            if (ID == id) {
                return;
            }
            ParentID.AddUnique(id);
            if (lat.Concepts.ContainsKey(id)) {
                lat.Concepts[id].AddChild(id);
            }
        }


        /// <summary>
        /// two way added
        /// </summary>
        /// <param name="c"></param>
        public void AddChild(Concept c) {
            if (c.ID == ID || ChildrenID.Contains(c.ID)) {
                return;
            }
            ChildrenID.AddUnique(c.ID);
            c.ParentID.AddUnique(ID);
            Tids = Tids.UnionWith(c.Tids);
        }

        /// <summary>
        /// one way added
        /// </summary>
        /// <param name="id"></param>
        public void AddChild(int id) {
            if (id == ID || ChildrenID.Contains(id)) return;
            ChildrenID.AddUnique(id);
        }

        /// <summary>
        /// two way added
        /// </summary>
        /// <param name="id"></param>
        /// <param name="lat"></param>
        public void AddChild(int id, Lattice lat) {
            if (ID == id || ChildrenID.Contains(id)) {
                return;
            }
            ChildrenID.Add(id);
            if (lat.Concepts.ContainsKey(id)) {
                lat.Concepts[id].AddParent(id);
            }
        }
        public void RemoveChild(Concept c) {
            if (ChildrenID.Contains(c.ID)) {
                ChildrenID.Remove(c.ID);
            }
            if (c.ParentID.Contains(ID)) {
                c.ParentID.Remove(ID);
            }
        }
        public void RemoveChild(int id) {
            if (ChildrenID.Contains(id)) {
                ChildrenID.Remove(id);
            }
        }
        public void RemoveParent(Concept c) {
            if (ParentID.Contains(c.ID)) {
                ParentID.Remove(c.ID);
            }
            if (c.ChildrenID.Contains(ID)) {
                c.ChildrenID.Remove(ID);
            }
        }
        public void RemoveParent(int id) {
            if (ParentID.Contains(id)) {
                ParentID.Remove(id);
            }
        }
        #endregion

        #region Add tids, items
        public void AddTid(int tid) {
            Tids.AddUnique(tid);
        }

        public void AddItem(int item) {
            Items.AddUnique(item);
        }
        #endregion
    }
}
